/**
 * Copyright (c) 2009 Teoti Graphix, LLC See:
 *     http://tkarchitecture.teotigraphix.org
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 * 
 * @author Michael Schmalle mschmalle@teotigraphix.com
 */
package test.suite.dxframework.core
{

import org.flexunit.Assert;
import org.flexunit.async.Async;
import org.fluint.uiImpersonation.UIImpersonator;
import org.teotigraphix.dx.core.ToolKitGlobals;
import org.teotigraphix.dx.core.ToolKitHelper;
import org.teotigraphix.dx.event.ModelLayerEvent;
import org.teotigraphix.dx.interfaces.IComponentModelCore;
import org.teotigraphix.dx.interfaces.IToolKitFactory;
import org.teotigraphix.dx.patterns.model.ComponentModelCore;

import test.suite.dxframework.support.behavior.TestAlternateComponentBehaviorCore;
import test.suite.dxframework.support.behavior.TestBehavior;
import test.suite.dxframework.support.behavior.TestComponentBehaviorCore;
import test.suite.dxframework.support.component.TestComponent;
import test.suite.dxframework.support.component.TestModelComponent;
import test.suite.dxframework.support.model.TestComponentModelCore;
import test.suite.dxframework.support.model.TestModel;


/**
 * Tests the <code>ToolKitHelper</code> properties API.
 * 
 * @author Michael Schmalle
 * @copyright Teoti Graphix, LLC
 * @date 07-22-09
 */
public class TC_ToolKitHelper
{
	//--------------------------------------------------------------------------
	//
	//  Private :: Variables
	//
	//--------------------------------------------------------------------------
	
	/**
	 * @private
	 */
	private var component:TestComponent;
	
	/**
	 * @private
	 */
	private var scomponent:TestModelComponent;
	
	//--------------------------------------------------------------------------
	//
	//  Overridden Protected :: Methods
	//
	//--------------------------------------------------------------------------
	
	[Before(ui)]
	/**
	 * @private
	 */
	public function setUp():void
	{
		ToolKitGlobals.VALIDATION_EVENTS_ENABLED = true;
		component = new TestComponent();
		scomponent = new TestModelComponent();
		UIImpersonator.addChild( component );
		UIImpersonator.addChild( scomponent );	
	}
	
	[After]
	/**
	 * @private
	 */
	public function tearDown():void
	{
		ToolKitGlobals.VALIDATION_EVENTS_ENABLED = false;
		
		UIImpersonator.removeChild( component );
		UIImpersonator.removeChild( scomponent );
		component = null;
		scomponent = null;
	}
	
	[Test]
	/**
	 * Tests the <code>dispatchPhase()</code> method.
	 */
	public function test_call_dispatchPhase():void
	{
		// TODO (mschmalle) impl unit test
	}
	
	[Test]
	/**
	 * Tests the <code>getToolKitFactory()</code> method.
	 */
	public function test_call_getToolKitFactory():void
	{
		var factory:IToolKitFactory = ToolKitHelper.getToolKitFactory(component);
		Assert.assertNotNull( "", factory );
	}
		
	//----------------------------------
	//  register/remove
	//----------------------------------
	
	[Test]
	/**
	 * Tests the <code>registerBehavior()</code> method.
	 */
	public function test_call_registerBehavior():void
	{
		Assert.assertFalse( "", component.behaviorLayer.hasBehavior( TestBehavior ) );
		var behavior:TestBehavior = new TestBehavior();
		ToolKitHelper.registerBehavior( component, TestBehavior, behavior );
		Assert.assertTrue( "", component.behaviorLayer.hasBehavior( TestBehavior ) );
	}
	
	[Test]
	/**
	 * Tests the <code>removeBehavior()</code> method.
	 */
	public function test_call_removeBehavior():void
	{
		Assert.assertFalse( "", component.behaviorLayer.hasBehavior( TestBehavior ) );
		var behavior:TestBehavior = new TestBehavior();
		ToolKitHelper.registerBehavior( component, TestBehavior, behavior );
		Assert.assertTrue( "", component.behaviorLayer.hasBehavior( TestBehavior ) );
		ToolKitHelper.removeBehavior( component, TestBehavior );
		Assert.assertFalse( "", component.behaviorLayer.hasBehavior( TestBehavior ) );
	}
	
	[Test]
	/**
	 * Tests the <code>registerModel()</code> method.
	 */
	public function test_call_registerModel():void
	{
		Assert.assertFalse( "", scomponent.modelLayer.hasModel( TestModel ) );
		var model:TestModel = new TestModel();
		ToolKitHelper.registerModel( scomponent, TestModel, model );
		Assert.assertTrue( "", scomponent.modelLayer.hasModel( TestModel ) );		
	}
	
	[Test]
	/**
	 * Tests the <code>removeModel()</code> method.
	 */
	public function test_call_removeModel():void
	{
		Assert.assertFalse( "", scomponent.modelLayer.hasModel( TestModel ) );
		var model:TestModel = new TestModel();
		ToolKitHelper.registerModel( scomponent, TestModel, model );
		Assert.assertTrue( "", scomponent.modelLayer.hasModel( TestModel ) );
		ToolKitHelper.removeModel( scomponent, TestModel );
		Assert.assertFalse( "", scomponent.modelLayer.hasModel( TestModel ) );
	}
	
	//----------------------------------
	//  set toolkit properties
	//----------------------------------
	
	[Test]
	/**
	 * Tests the <code>setCoreBehavior()</code> method.
	 */
	public function test_call_setCoreBehavior():void
	{
		Assert.assertTrue( "component.coreBehavior not TestComponentBehaviorCore", 
			(component.coreBehavior is TestComponentBehaviorCore) );
		
		// sets the component on the coreBehavior
		var oldCore:TestComponentBehaviorCore = TestComponentBehaviorCore(component.coreBehavior);
		var newCore:TestAlternateComponentBehaviorCore = new TestAlternateComponentBehaviorCore();
		
		// this is a asyncronous call
		component.coreBehavior = newCore;
		component.validateProperties();
		// ToolKitManager then calls
//		ToolKitHelper.setCoreBehavior( component, newCore, oldCore );

		Assert.assertStrictlyEquals( "newCore not TestAlternateComponentBehaviorCore", 
			newCore, component.coreBehavior );
		
		// check that things got dereferenced on the oldCore
		Assert.assertNull( oldCore.component );
		Assert.assertNull( oldCore.uicomponent );
		Assert.assertNull( oldCore.myPart );
		Assert.assertNull( oldCore.testComponent );
		
//		Assert.assertNull( oldCore.behaviorLayer );
//		Assert.assertNull( oldCore.serviceLayer );
		
		// check that things got referenced on the newCore
		Assert.assertStrictlyEquals( "", newCore.component, component );
		Assert.assertStrictlyEquals( "", newCore.uicomponent, component );
		
//		Assert.assertStrictlyEquals( "newCore.behaviorLayer", 
//			newCore.behaviorLayer, component.behaviorLayer );
//		Assert.assertStrictlyEquals( "newCore.modelLayer", 
//			newCore.modelLayer, component.modelLayer );
	}
	
	[Test(async)]
	/**
	 * Tests the <code>setCoreModel()</code> method.
	 */
	public function test_call_setCoreModel():void
	{
		var o:Object = {};
		
		Assert.assertTrue( "component.coreService not TestComponentModelCore", 
			(component.coreModel is TestComponentModelCore) );
		
		// sets the component on the coreService
		var oldCore:TestComponentModelCore = TestComponentModelCore(component.coreModel);
		var newCore:ComponentModelCore = new ComponentModelCore();
		
		o.component = component;
		o.api = IComponentModelCore;
		o.oldCore = oldCore;
		o.newCore = newCore;
		
		Async.handleEvent( this, component, ModelLayerEvent.MODEL_REMOVE,
			component_setCoreModel_serviceRemove_Handler, 500, o );
		Async.handleEvent( this, component, ModelLayerEvent.MODEL_ADD,
			component_setCoreModel_serviceAdd_Handler, 500, o );
		
		// this is a asyncronous call
		component.coreModel = newCore;
		component.validateProperties();
		// ToolKitManager then calls
//		ToolKitHelper.setCoreService( component, newCore, oldCore );

		Assert.assertStrictlyEquals( "newCore not CoreComponentService", 
			newCore, component.coreModel );
		
		Assert.assertNull( "", oldCore.component );
		Assert.assertNotNull( "", newCore.component );
		
		Assert.assertStrictlyEquals( "newCore.component", 
			component, newCore.component );
		
		// check compoennt	
	}
	
	
	/**
	 * Tests the <code>setBehaviorLayer()</code> method.
	 */
	public function test_call_setBehaviorLayer():void
	{
	}
	
	/**
	 * Tests the <code>setBehaviors()</code> method.
	 */
	public function test_call_setBehaviors():void
	{
	}
	
	/**
	 * Tests the <code>setModelLayer()</code> method.
	 */
	public function test_call_setModelLayer():void
	{
	}
	
	/**
	 * Tests the <code>setModels()</code> method.
	 */
	public function test_call_setModels():void
	{
	}
	
	/**
	 * Tests the <code>setSkinLayer()</code> method.
	 */
	public function test_call_setSkinLayer():void
	{
	}
	
	/**
	 * Tests the <code>setToolKitFactory()</code> method.
	 */
	public function test_call_setToolKitFactory():void
	{
	}
	
	
	
	
	//--------------------------------------------------------------------------
	//
	//  Protected :: Handlers
	//
	//--------------------------------------------------------------------------
	
	/**
	 * @private
	 */
	protected function component_setCoreModel_serviceRemove_Handler( event:ModelLayerEvent, data:Object ):void 
	{
		Assert.assertEquals( "event.type", ModelLayerEvent.MODEL_REMOVE, event.type );
		Assert.assertStrictlyEquals( "event.service", data.oldCore, event.model );
		Assert.assertStrictlyEquals( "event.api", data.api, event.api );
		Assert.assertStrictlyEquals( "event.component", data.component, event.component );
	}
	
	/**
	 * @private
	 */
	protected function component_setCoreModel_serviceAdd_Handler( event:ModelLayerEvent, data:Object ):void 
	{
		Assert.assertEquals( "event.type", ModelLayerEvent.MODEL_ADD, event.type );
		Assert.assertStrictlyEquals( "event.service", data.newCore, event.model );
		Assert.assertStrictlyEquals( "event.api", data.api, event.api );
		Assert.assertStrictlyEquals( "event.component", data.component, event.component );		
	}
	
}
}